/* Copyright 2002 -- Ira R. Forman and Nate Forman */ 
/**
 * This transformation produces a class that keeps a list of all
 * of the instances of the class.  Note that because all the constructors
 * of a subclass must call one of the constructors created by this transformation,
 * the extent-managed property is in effect inherited by all subclasses.
 * The extent of a class is maintained using weak references.  This implies
 * that the extent managed property does not interfere with garbage collection.
 * 
 * The extent of a class may be retrieved with the getExtent static method,
 * which is added by this transformation, too.
 */
//start extract C2ExtentManagedC
package c2c;
import java.lang.reflect.*;
import java.io.Serializable;
import mopex.*;

public class C2ExtentManagedC extends C2CTransformation {

    private int numberOfConstructors = 0;

    static public void main( String[] args ) {                       //#1
	new C2ExtentManagedC().createClass( args );                  //#1
    }    

    protected UQueue generateImports() {                             //#2
	return super.generateImports()                               //#2
	            .add("java.util.Vector")                         //#2
	            .add("java.lang.ref.*");                         //#2
    }

    protected String generateClassNamePrefix() {
	return "ExtentManaged" + super.generateClassNamePrefix();    //#3
    }

    protected String getSuperclass() {return inputClassName;}        //#4

    protected void checkAndProcessArgs( Args args ) {                //#5
	super.checkAndProcessArgs( args );
	if ( Serializable.class.isAssignableFrom(inputClassObject) )
	    throw new C2CException("cannot handle Serializable input classes");
	if ( Cloneable.class.isAssignableFrom(inputClassObject) )
	    throw new C2CException("Cloneable and Singleton are conflicting");
    }

    protected String generateFields() {
	return super.generateFields() 
	    + "    static private Vector myExtent = new Vector();\n"; //#6
    }

    protected String generateConstructors() {                         //#7
	String managementCode = 
	    "    myExtent.add( new WeakReference(this) );\n";
	String overriddenConstructors = "";
	Constructor[] cArray = inputClassObject.getDeclaredConstructors();
	if ( cArray.length != 0 ) {
	    for (int i = 0; i < cArray.length; i++ ) 
		overriddenConstructors 
		    += Modifier.toString( cArray[i].getModifiers() ) 
		    + " "
		    + Mopex.createRenamedConstructor( cArray[i], 
						      outputClassName,
						      managementCode );
	    numberOfConstructors = cArray.length; 
	} else {
	    overriddenConstructors = outputClassName
		                   + "()\n    {\n" 
		                   + managementCode 
                                   + "    }\n";
	    numberOfConstructors = 1; 
	}
	return super.generateConstructors() + overriddenConstructors;
    }

    protected String generateMethods() {                               //#8
	return super.generateMethods() 
	    + "    static public " + outputClassName + "[] getExtent() {\n"
	    + "        Vector extent = new Vector();\n"
	    + "        for (int i = myExtent.size()-1, j = 0; i >= 0; i--) {\n"
	    + "            " + outputClassName + " anObj = \n" 
	    + "                (" + outputClassName + ")\n" 
	    + "                ((WeakReference)myExtent.elementAt(i)).get();\n"
	    + "            if ( anObj != null )\n"
	    + "                extent.add(anObj);\n"
	    + "            else\n"
	    + "                myExtent.remove(i);\n"
	    + "        }\n"
	    + "        return (" + outputClassName + "[])\n"
	    + "               extent.toArray( new " + outputClassName + "[1]);\n"
	    + "    }\n";
    }

    protected void checkPostconditions() {                             //#9
	super.checkPostconditions();
	if ( outputClassObject.getDeclaredConstructors().length 
	     != numberOfConstructors )
	    throw new C2CException( "non-ExtentManaged constructors added" );
    }
}
//stop extract C2ExtentManagedC
